#include <conversions.h>

// Get full list of name (display = true for Human, false for computer)
QStringList PitchNoteList(bool disp, bool lat)
{
    QStringList list;
    if (disp) {
        if (lat) return list  << "La" << "Si" << "Do" << "Re" << "Mi" << "Fa" << "Sol";
        else return list << "A" << "B" << "C" << "D" << "E" << "F" << "G";
    } else {
        if (lat) return list  << "la" << "si" << "do" << "re" << "mi" << "fa" << "sol";
        else return list << "a" << "b" << "c" << "d" << "e" << "f" << "g";
    }
}

QStringList AlterNoteList(bool disp)
{
    QStringList list;
    if (disp) return list << "bb" << "b" << "" << "#" << "##";
    else return list << "doubleflat" << "flat" << "natural" << "sharp" << "doublesharp";
}

QStringList EquiNoteList(bool disp, bool lat)
{
    QStringList list;
    if (disp) {
        if (lat) return list  << "La" << "Sib" << "Si" << "Do" << "Reb" << "Re"<< "Mib" << "Mi" << "Fa"<< "Solb" << "Sol" << "Lab";
        else return list << "A" << "Bb" << "B" << "C" << "Des" << "D" << "Ees" << "E" << "F" << "Ges" << "G" << "Aes";
    } else {
        if (lat) return list  << "la" << "sib" << "si" << "do" << "reb" << "me"<< "mib" << "mi" << "fa"<< "solb" << "sol" << "lab";
        else return list << "a" << "bb" << "b" << "c" << "des" << "d" << "ees" << "e" << "f" << "ges" << "g" << "aes";
    }
}

QStringList OctaveList(bool disp)
{
    QStringList list;
    if (disp) return list << "-1" << "0" << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8";
    else return list << "c-1" << "c0" << "c1" << "c2" << "c3" << "c4" << "c5" << "c6" << "c7" << "c8";
}

QStringList ClefList(bool disp)
{
    QStringList list;
    if (disp) return list << "Treble" << "Tenor" << "Bass";
    else return list << "treble" << "tenor" << "bass";
}

QStringList TemperamentList(bool disp)
{
    QStringList list;
    if (disp) return list << "Equal temperament" << "Pitagorean (discard Gb)" << "Pitagorean (discard F#)";
    else return list << "equal" << "pitagoreanup" << "pitagoreandown";
}

Temperament toTemperament(QString str)
{
    QRegExp exp = QRegExp ( str, Qt::CaseInsensitive );
    int index = TemperamentList(true).indexOf(exp);
    if(index == -1) index = TemperamentList(false).indexOf(exp);
    if(index == -1) qWarning() << "Temperament not found:" << str;
    return toTemperament(index);
}

Temperament toTemperament(int index)
{
    if(index == 0) return Equal;
    else if(index == 1) return PitagoreanUp;
    else if(index == 2) return PitagoreanDown;
    else qWarning() << "Temperament not found" << index;
}

// Replace stupid C integer difision
// Down approx division
int MathDivide(int a, int b)
{
    int r;
    if (a >= 0) r = a/b;
    else r = (a-b+1)/b;
    return r;
}

// No negative reminder
int MathReminder(int a, int b)
{
    int r;
    if (a >= 0) r = a%b;
    else r = (a%b + b != 12 ? a%b + b : 0);
    //qDebug() << "Dividing" << a << "with" << b << "to get" << r;
    Q_ASSERT_X(r >= 0 && r < 12, "Debugging MathReminder!", "Gotcha!");
    return r;
}

// Conversion talbe (cents and frequencies ratios)
int centsDiff(qreal freq1, qreal freq2) {
    return int(1200 * qLn(freq2/freq1) / qLn(2));
}

//qreal fromFreqCentsDiff(qreal freq, int cents) {
//    qreal c = qreal(cents) / qreal(1200);
//   return qPow(2, c) * freq;
//}

qreal getRatioFreq(int cent_diff, Temperament temp)
{
    qreal ratio;
    int octave, reminder;
    switch(temp) {
    case Equal:
        ratio = qPow(2, qreal(cent_diff) / qreal(1200));
        //qDebug() << "Ratio:" << ratio;
        break;
    case PitagoreanUp:
        octave = MathDivide(cent_diff,1200);
        reminder = cent_diff - octave * 1200;
        if (reminder == 0) ratio = 1;
        else if (reminder == 100) ratio = 256.0/243.0;
        else if (reminder == 200) ratio = 9.0/8.0;
        else if (reminder == 300) ratio = 32.0/27.0;
        else if (reminder == 400) ratio = 81.0/64.0;
        else if (reminder == 500) ratio = 4.0/3.0;
        else if (reminder == 600) ratio = 729.0/512.0;
        else if (reminder == 700) ratio = 3.0/2.0;
        else if (reminder == 800) ratio = 128.0/81.0;
        else if (reminder == 900) ratio = 27.0/16.0;
        else if (reminder == 1000) ratio = 16.0/9.0;
        else if (reminder == 1100) ratio = 243.0/128.0;
        ratio *= qPow(2, octave);
        break;
    case PitagoreanDown:
        octave = MathDivide(cent_diff,1200);
        reminder = cent_diff - octave * 1200;
        if (reminder == 0) ratio = 1;
        else if (reminder == 100) ratio = 256.0/243.0;
        else if (reminder == 200) ratio = 9.0/8.0;
        else if (reminder == 300) ratio = 32.0/27.0;
        else if (reminder == 400) ratio = 81.0/64.0;
        else if (reminder == 500) ratio = 4.0/3.0;
        else if (reminder == 600) ratio = 1024.0/729.0;
        else if (reminder == 700) ratio = 3.0/2.0;
        else if (reminder == 800) ratio = 128.0/81.0;
        else if (reminder == 900) ratio = 27.0/16.0;
        else if (reminder == 1000) ratio = 16.0/9.0;
        else if (reminder == 1100) ratio = 243.0/128.0;
        ratio *= qPow(2, octave);
        break;
    }
    //qDebug() << "Octave:" << octave << "Reminder:" << reminder;
    //qDebug() << "Cent diff:" << cent_diff << "Ratio:" << ratio;
    return ratio;
}

